package site.isscloud.jt809;

import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Arrays;

public class JT809Utils {
    // 消息头标识
    public static final byte[] MSG_HEAD = new byte[]{(byte) 0x30, (byte) 0x31, (byte) 0x63, (byte) 0x64};
    
    // 计算CRC16校验码 (简化版，实际应使用标准CRC16算法)
    public static short calculateCRC16(byte[] data) {
        int crc = 0xFFFF;
        for (byte b : data) {
            crc ^= (b & 0xFF) << 8;
            for (int i = 0; i < 8; i++) {
                if ((crc & 0x8000) != 0) {
                    crc = (crc << 1) ^ 0x1021;
                } else {
                    crc <<= 1;
                }
            }
            crc &= 0xFFFF;
        }
        return (short) crc;
    }
    
    // 生成MD5密码
    public static byte[] md5_20(String input) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(input.getBytes("UTF-8"));
            byte[] result = new byte[20];
            int startPos = 20 - digest.length;
            if (startPos > 0) {
                System.arraycopy(digest, 0, result, startPos, digest.length);
            } else {
                System.arraycopy(digest, -startPos, result, 0, 20);
            }
            return result;
        } catch (Exception e) {
            throw new RuntimeException("MD5计算失败", e);
        }
    }
    
    // 字节数组转十六进制字符串
    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString();
    }
    
    // 检查消息头是否正确
    public static boolean checkMsgHead(byte[] head) {
        return Arrays.equals(head, MSG_HEAD);
    }
    
    // 读取无符号short
    public static int readUnsignedShort(ByteBuffer buffer) {
        return buffer.getShort() & 0xFFFF;
    }
    
    // 读取无符号int
    public static long readUnsignedInt(ByteBuffer buffer) {
        return buffer.getInt() & 0xFFFFFFFFL;
    }

    // 将long类型时间转换为byte[6]
    public static byte[] longToByteArray(long time) {
        byte[] result = new byte[6];
        result[0] = (byte) ((time / 10000000000L) % 100); // 年
        result[1] = (byte) ((time / 100000000L) % 100);   // 月
        result[2] = (byte) ((time / 1000000L) % 100);     // 日
        result[3] = (byte) ((time / 10000L) % 100);       // 时
        result[4] = (byte) ((time / 100L) % 100);         // 分
        result[5] = (byte) (time % 100);                 // 秒
        return result;
    }

    // 将byte[6]转换回long
    public static long byteArrayToLong(byte[] time) {
        return (time[0] & 0xFF) * 10000000000L +
               (time[1] & 0xFF) * 100000000L +
               (time[2] & 0xFF) * 1000000L +
               (time[3] & 0xFF) * 10000L +
               (time[4] & 0xFF) * 100L +
               (time[5] & 0xFF);
    }

    // 将byte[6]转换为YYMMDDHHMMSS格式的字符串
    public static String byteArrayToString(byte[] time) {
        return String.format("%02d%02d%02d%02d%02d%02d",
                time[0] & 0xFF, time[1] & 0xFF, time[2] & 0xFF,
                time[3] & 0xFF, time[4] & 0xFF, time[5] & 0xFF);
    }
    
    /**
     * 解析JT809消息
     * @param in 输入流
     * @return JT809Message对象
     * @throws IOException
     */
    public static JT809Message parseJT809Message(InputStream in) throws IOException {
        // 读取消息头(4字节)
        byte[] header = new byte[4];
        readFully(in, header);
        
        if (!checkMsgHead(header)) {
            throw new IOException("Invalid message header");
        }
        
        // 读取消息ID(2字节)和消息长度(4字节)
        byte[] idAndLength = new byte[6];
        readFully(in, idAndLength);
        
        ByteBuffer buffer = ByteBuffer.wrap(idAndLength).order(ByteOrder.BIG_ENDIAN);
        // int msgId = readUnsignedShort(buffer);
        readUnsignedShort(buffer); // 跳过消息ID
        int msgLen = buffer.getInt();
        
        // 计算剩余部分长度: 
        // 消息流水号(4) + 平台ID(4) + 版本号(3) + 加密标志(1) + 加密密钥(4) + 消息体(msgLen) + CRC(2)
        int remainingLength = 4 + 4 + 3 + 1 + 4 + msgLen + 2;
        byte[] remaining = new byte[remainingLength];
        readFully(in, remaining);
        
        // 组合完整消息
        byte[] fullMessage = new byte[4 + 6 + remainingLength];
        System.arraycopy(header, 0, fullMessage, 0, 4);
        System.arraycopy(idAndLength, 0, fullMessage, 4, 6);
        System.arraycopy(remaining, 0, fullMessage, 10, remainingLength);
        
        return new JT809Message(fullMessage);
    }

    // 确保读取指定长度的数据
    private static void readFully(InputStream in, byte[] buffer) throws IOException {
        int totalRead = 0;
        while (totalRead < buffer.length) {
            int read = in.read(buffer, totalRead, buffer.length - totalRead);
            if (read == -1) {
                throw new EOFException("Unexpected end of stream");
            }
            totalRead += read;
        }
    }

     // 字符串转字节数组(固定长度)
     public static byte[] stringToBytes(String str, int length) {
        byte[] bytes = new byte[length];
        if (str != null) {
            byte[] srcBytes = str.getBytes(StandardCharsets.UTF_8);
            System.arraycopy(srcBytes, 0, bytes, 0, Math.min(srcBytes.length, length));
        }
        return bytes;
    }
    
    // 字节数组转字符串(去除空字符)
    public static String bytesToString(byte[] bytes) {
        int length = 0;
        while (length < bytes.length && bytes[length] != 0) {
            length++;
        }
        return new String(bytes, 0, length, StandardCharsets.UTF_8);
    }
}
